package automaton.view;

import java.awt.Dimension;

import javax.crypto.IllegalBlockSizeException;

/**
 * Matriz de booleanos redimension�vel.
 * @author Grupo 6
 *
 */
public class BooleanMatrix {

	/**
	 * a matriz
	 */
	private boolean[][] matriz;
	
	/**
	 * tamanho da matriz no momento
	 */
	private Dimension tamanho;
	
	/**
	 * Instancia a matriz com linha de acordo com a propriedade height do obj dimension passado
	 * e colunas de acordo com o width.
	 * @param d dimensoes da matriz
	 */
	public BooleanMatrix(Dimension d)
	{
		this.matriz = new boolean[d.width][d.height];
		this.tamanho = d;
	}
	
	/**
	 * Retorna quantas colunas a matriz tem
	 * @return quantidade de colunas
	 */
	public int getWidth()
	{
		return this.tamanho.height;
	}
	
	/**
	 * Retorna quantas linhas a matriz tem
	 * @return largura
	 */
	public int getHeight()
	{
		return this.tamanho.width;
	}
	
	/**
	 * Retorna o valor (true ou false) na celula cujos indices sao passados por parametro
	 * @param pLinha indice da linha da celula
	 * @param pColuna indice da coluna da celula
	 * @return valor booleano desta celula
	 * @throws ArrayIndexOutOfBoundsException
	 */
	public boolean getCell(int pLinha, int pColuna) throws ArrayIndexOutOfBoundsException
	{
		return this.matriz[pLinha][pColuna];
	}

	/**
	 * Atribui o valor pValue a celula pLinha e pColuna
	 * @param pLinha indice da linha da celula a ser atualizada
	 * @param pColuna indice da coluna da celula a ser atualizada
	 * @param pValue valor da celula
	 */
	public void setCell(int pLinha, int pColuna, boolean pValue)
	{
		this.matriz[pLinha][pColuna] = pValue;
	}
	
	/**
	 * Redimensiona a matriz com as dimensoes que sao passadas por parametro.
	 * Se a matriz for diminuida, as celulas que sao perdidas nao podem ter 
	 * seu valor recuperado.
	 * @param d novas dimensoes da tabela.
	 */
	public void resize(Dimension d)
	{
		boolean[][] lNovaMatriz = new boolean[d.width][d.height];
		int lContaLinha, lContaColuna,
			lMaxLinha, lMaxColuna;
		
		// Menor Linha entre a nova e o velha matriz
		if(d.width < this.getHeight())
		{
			lMaxLinha = d.width;
		} else {
			lMaxLinha = this.getHeight();
		}

		
		// Menor Coluna
		if(d.height < this.getWidth())
		{
			lMaxColuna = d.height;
		} else {
			lMaxColuna = this.getWidth();
		}
		
		// Reatribuindo valores na nova
		for(lContaLinha=0;lContaLinha<lMaxLinha;lContaLinha++)
		{
			for(lContaColuna=0;lContaColuna<lMaxColuna;lContaColuna++)
			{
				lNovaMatriz[lContaLinha][lContaColuna] = this.matriz[lContaLinha][lContaColuna];
			}
		}
		this.tamanho = d;
		this.matriz = lNovaMatriz;
	}
	
	/**
	 * Retorna uma copia da linha cujo indice eh passado por parametro
	 * @param pLinha indice da linha que se deseja a copia
	 * @return vetor de boolean com a linha desejada
	 */
	public boolean[] getRow(int pLinha)
	{
		return this.matriz[pLinha];
	}
	/**
	 * Retorna a ultima linha da matriz
	 * @return vetor de boolean com a ultima linha da matriz
	 */
	public boolean[] getLastRow()
	{
		return this.matriz[this.matriz.length-1];
	}
	
	/**
	 * Adiciona uma linha ao final do vetor
	 * @param r vetor de boolean, a linha que sera adicionada
	 */
	public void addRow(boolean[] r) throws IllegalBlockSizeException
	{
		if(r.length != this.getWidth())
		{
		  throw new IllegalBlockSizeException("O vetor tem tamanho incompativel com a matriz");	
		}
		this.resize(new Dimension(this.getHeight()+1,this.getWidth()));
		this.matriz[this.matriz.length-1] = r;		
	}

	/**
	 * Cria uma copia exata da matriz de booleanos
	 */
	public BooleanMatrix clone()
	{
		BooleanMatrix lNovaMatriz = new BooleanMatrix(this.tamanho);
		int lContaLinha, lContaColuna;

		for(lContaLinha=0;lContaLinha < this.tamanho.height;lContaLinha++)
		{
			for(lContaColuna=0;lContaColuna < this.tamanho.width;lContaColuna++)
			{
				lNovaMatriz.matriz[lContaLinha][lContaColuna] = this.matriz[lContaLinha][lContaColuna];
			}
		}
		return lNovaMatriz;
	}
}
